// 设计一个可以保存任意类型的容器类，且构造时不需要显式实例化
#include <cassert>
#include <typeinfo>
#include <algorithm>
#include <iostream>
#include <string>
#include <unistd.h>
class Any
{
private:
    // 内部的父类
    class Holder
    {
    public:
        virtual ~Holder() {};
        // 构造新的子类返回（用于Any的拷贝构造）
        virtual Holder *CopyNewOne() = 0;
        // 返回子类的类型-注意type_info拷贝构造被删除，用引用接受（用于对比Get时的类型是否正确）
        virtual const std::type_info &GetTypeInfo() = 0;
    };

    // 子类-未来会存任意的类型
    template <class T>
    class PalceHolder : public Holder
    {
    public:
        // 直接根据对象构造
        PalceHolder(const T &val) : _val(val)
        {
        }
        ~PalceHolder() {};
        // 构造新的子类返回（用于Any的拷贝构造）
        virtual Holder *CopyNewOne() override
        {
            return new PalceHolder(_val);
        }

        virtual const std::type_info &GetTypeInfo() override
        {
            return typeid(T);
        }

    public:
        T _val; // 实际存储的任意T类型
    };

    void Swap(Any &other)
    {
        std::swap(_content, other._content);
    }

public:
    // 空构造函数
    Any() : _content(nullptr)
    {
    }
    // 根据任意对象直接构造
    template <class T>
    Any(const T &val) : _content(new PalceHolder<T>(val))
    {
    }
    // 拷贝构造
    Any(const Any &other) : _content(other._content ? other._content->CopyNewOne() : nullptr) // 如果是空Any对象，则直接赋值空，如果不是，则根据子类构造一个新的子类返回
    {
    }
    ~Any()
    {
        if (_content)
            delete _content;
    }
    // 赋值操作符-根据对象直接赋值
    template <class T>
    Any &operator=(const T &val)
    {
        Any any(val);
        Swap(any); // 直接根据val构造一个临时对象与之交换，临时对象会自动销毁
        return *this;
    }
    //  赋值操作符-根据Any对象赋值
    Any &operator=(Any other)
    {
        // 直接传值接收，会先调用拷贝构造，构造出临时的对象other，再交换即可，省去主动delete的过程
        Swap(other);
        return *this;
    }

    // 获取存储的对象，外部会显式传递类型
    template <class T>
    T *Get()
    {
        // 断言一下外部传的类型一定是与存储的类型相同
        assert(typeid(T) == _content->GetTypeInfo());
        if (_content == nullptr)
            return nullptr;
        // 返回内部的对象
        return &(((PalceHolder<T> *)_content)->_val);
    }

    Holder *_content;
};

// class Any
// {
// public:
//     Any() : _content(NULL) {}
//     /*为了能够接收所有类型的对象，因此将构造函数定义为⼀个模板函数*/
//     template <typename T>
//     Any(const T &val) : _content(new holder<T>(val)) {}
//     Any(const Any &other) : _content(other._content ? other._content->clone()
//                                                     : NULL) {}
//     ~Any()
//     {
//         if (_content)
//             delete _content;
//     }
//     const std::type_info &type() { return _content ? _content->type() : typeid(void); }
//     Any &swap(Any &other)
//     {
//         std::swap(_content, other._content);
//         return *this;
//     }
//     template <typename T>
//     T *get()
//     {
//         assert(typeid(T) == _content->type());
//         return &((holder<T> *)_content)->val;
//     }
//     template <typename T>
//     Any &operator=(const T &val)
//     {
//         /*为val构建⼀个临时对象出来，然后进⾏交换，这样临时对象销毁的时候，顺带原先
//        保存的placeholder也会被销毁*/

//         Any(val).swap(*this);
//         return *this;
//     }
//     Any &operator=(Any other)
//     {
//         /*这⾥要注意形参只是⼀个临时对象，进⾏交换后就会释放，所以交换后，原先保存的
//        placeholder指针也会被销毁*/
//         other.swap(*this);
//         return *this;
//     }

// private:
//     /*因为模板类编译时就会确定类型，因此*/
//     class placeholder
//     {
//     public:
//         virtual ~placeholder() {}
//         virtual const std::type_info &type() = 0;
//         virtual placeholder *clone() = 0;
//     };
//     /*当前的Any类中⽆法保存所有类型的对象，或者说不能整成模板类，因此声明⼀个holder
//    模板类出来使⽤holder类来管理传⼊的对象*/
//     /*⽽Any类只需要管理holder对象即可*/
//     template <typename T>
//     class holder : public placeholder
//     {
//     public:
//         holder(const T &v) : val(v) {}
//         ~holder() {}
//         const std::type_info &type() { return typeid(T); }
//         placeholder *clone() { return new holder(val); }

//     public:
//         T val;
//     };
//     placeholder *_content;
// };

#include <any> //测试C++17any容器
class Test
{
public:
    Test() { std::cout << "Test()" << std::endl; }
    Test(const Test &) { std::cout << "Test(const Test&)" << std::endl; }
    ~Test() { std::cout << "~Test()" << std::endl; }
};
int main()
{
    // std::any a;
    // a = 10;
    // int* pint  = std::any_cast<int>(&a);
    // std::cout<<*pint<<std::endl;

    // a = std::string("haaaaa");
    // std::string* pstr = std::any_cast<std::string>(&a);
    // std::cout<<*pstr<<std::endl;

    // Any a;
    // {
    //     Test t;
    //     a = t;
    // }

    // a = 1;
    // int *pint = a.Get<int>();
    // std::cout << *pint << std::endl;
    // a = std::string("hahaha");
    // std::string *ps = a.Get<std::string>();
    // std::cout << *ps << std::endl;
    while (1)
        sleep(1);
    return 0;
}


